Algorithms.7

矩阵

代码

  • 旋转
from copy import deepcopy


def rotate90(m):
    el_len = len(m[0])
    new_m = [[0]*len(m) for _ in range(el_len)]
    for i, row in enumerate(m):
        for j, elem in enumerate(row):
            new_m[el_len-1-j][i] = elem

    return new_m


def rotate180(m):
    for row in m:
        row = row.reverse()

    return m


def rotate270(m):
    new_m = [[0]*len(m) for _ in range(len(m[0]))]
    for i, row in enumerate(m):
        for j, elem in enumerate(row):
            new_m[j][i] = elem

    return new_m


if __name__ == "__main__":
    m = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]

    m1 = deepcopy(m)
    assert rotate90(m1) == [[4, 8, 12], [3, 7, 11], [2, 6, 10], [1, 5, 9]]

    m1 = deepcopy(m)
    assert rotate180(m1) == [[4, 3, 2, 1], [8, 7, 6, 5], [12, 11, 10, 9]]

    m1 = deepcopy(m)
    assert rotate270(m1) == [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
  • 炸弹人
Given a 2D grid, each cell is either a wall 'W',
an enemy 'E' or empty '0' (the number zero),
return the maximum enemies you can kill using one bomb.
The bomb kills all the enemies in the same row and column from
the planted point until it hits the wall since the wall is too strong
to be destroyed.
Note that you can only put the bomb at an empty cell.
Example:
For the given grid
0 E 0 0
E 0 W E
0 E 0 0
return 3. (Placing a bomb at (1,1) kills 3 enemies)

思路: 逐一查看行和列

import numpy as np


def bomb_row(row, index):
    kills = 0
    step = index
    while step > 0:
        step -= 1
        if row[step] == "e":
            kills += 1
        elif row[step] == "w":
            break

    step = index
    while step < len(row)-1:
        step += 1
        if row[step] == "e":
            kills += 1
        elif row[step] == "w":
            break

    return kills


def bomb_enemy(grid):
    kills = 0
    for i, row in enumerate(grid):
        for j, elm in enumerate(row):
            if elm == "0":
                kills = max(kills, bomb_row(row, j)+bomb_row(grid[:, j], i))

    return kills


if __name__ == "__main__":
    grid = np.asarray([[0, "e", 0, 0, "e"],
                       ["e", 0, "e", "w", "e"],
                       [0, "e", 0, 0, 0],
                       [0, "e", 0, 0, 0]
                       ])
    assert bomb_enemy(grid) == 5
  • 稀疏矩阵点乘

"”” Given two sparse matrices A and B, return the result of AB. You may assume that A’s column number is equal to B’s row number. Example: A = [ [ 1, 0, 0], [-1, 0, 3] ] B = [ [ 7, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 1 ] ] | 1 0 0 | | 7 0 0 | | 7 0 0 | AB = | -1 0 3 | x | 0 0 0 | = | -7 0 3 | | 0 0 1 | "””

思路:找出非零的然后计算

import numpy as np


def multiply(a, b):
    ar, ae = a.shape
    br, be = b.shape
    assert ae == br

    c = np.zeros([ar, be])

    for i, arow in enumerate(a):
        for j, aelem in enumerate(arow):
            if aelem:
                for k, belem in enumerate(b[j]):
                    if belem:
                        c[i, k] += belem*aelem

    return c


if __name__ == "__main__":
    a = np.array([[1, 0, 0],
                  [-1, 0, 3]])

    b = np.array([[7, 0, 0],
                  [0, 0, 0],
                  [0, 0, 1]])

    print(multiply(a, b))
  • 旋转遍历

"”” Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. For example, Given the following matrix: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] You should return [1,2,3,6,9,8,7,4,5]. "””

思路:分方向,给出起始坐标,不停更新矩阵

import numpy as np


def skip(matrix, direction, i, j, res):
    n, m = matrix.shape
    if direction == 0:
        while j < m:
            res.append(matrix[i, j])
            j += 1
        matrix = matrix[i+1:, :]
        n, m = matrix.shape
        return matrix, 0, m-1, 1

    elif direction == 1:
        while i < n:
            res.append(matrix[i, j])
            i += 1
        matrix = matrix[:, :m-1]
        n, m = matrix.shape
        return matrix, n-1, m-1, 2

    elif direction == 2:
        while j >= 0:
            res.append(matrix[i, j])
            j -= 1

        matrix = matrix[:n-1, :]
        n, m = matrix.shape
        return matrix, n-1, 0, 3
    else:
        while i >= 0:
            res.append(matrix[i, j])
            i -= 1
        return matrix[:, j+1:], 0, 0, 0


def spiral_traversal(matrix):
    res, direction = [], 0
    n, m = matrix.shape
    i, j = 0, 0
    while len(res) < n*m:
        matrix, i, j, direction = skip(matrix, direction, i, j, res)

    return res


if __name__ == "__main__":
    mat = np.asarray([[1, 2, 3, 4],
                      [5, 6, 7, 8],
                      [9, 10, 11, 12],
                      [13, 14, 15, 16]])
    assert spiral_traversal(
        mat) == [1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10]
  • 计算路径

"”” Count the number of unique paths from a[0][0] to a[m-1][n-1] We are allowed to move either right or down from a cell in the matrix. Approaches- (i) Recursion- Recurse starting from a[m-1][n-1], upwards and leftwards, add the path count of both recursions and return count. (ii) Dynamic Programming- Start from a[0][0].Store the count in a count matrix. Return count[m-1][n-1] T(n)- O(mn), S(n)- O(mn) "””

思路:和爬梯子一样,斐波那契数

import numpy as np


def count_paths(m, n):
    if m < 1 or n < 1:
        return -1

    count = np.zeros((n, m))
    count[0, :] = 1
    count[:, 0] = 1

    for i in range(1, n):
        for j in range(1, m):
            count[i, j] = count[i, j-1] + count[i-1, j]

    return count[-1, -1]


if __name__ == "__main__":
    assert count_paths(3, 4) == 10
Nevermore Written by:

步步生姿,空锁满庭花雨。胜将娇花比。